﻿using FastApi.Attributes;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace FastApi
{
    public class FastApp
    {
        #region 静态变量

        public readonly Dictionary<string, FastModule> FastModuleDict = [];

        #endregion

        #region 变量

        private readonly WebApplication webApp;

        internal readonly Dictionary<RuntimeTypeHandle, FastParamCreator> ParamCreatorDict = [];

        internal readonly List<FastFilter> FilterList = [];

        #endregion

        #region 路由匹配

        private async ValueTask AfterAsync(FastContext fastCtx)
        {
            if (OnAfterRequestAsync != null)
            {
                try
                {
                    await OnAfterRequestAsync.Invoke(fastCtx);
                }
                catch { }
            }
        }

        /// <summary>
        /// 路由匹配
        /// </summary>
        /// <param name="route"></param>
        private void MapRoute(string route)
        {
            webApp.MapWhen(ctx =>
            {
                if (ctx.Request.Path.HasValue)
                {
                    return ctx.Request.Path.Value.StartsWith(route, StringComparison.OrdinalIgnoreCase);
                }
                return false;

            }, builder =>
            {
                builder.Run(async context =>
                {
                    var module = FastModuleDict[route];

                    var nameSpan = context.Request.Path.Value.AsMemory()[route.Length..];

                    #region Action Null 404

                    if (nameSpan.Length <= 0)
                    {
                        context.Response.StatusCode = 404;
                        return;
                    }
                    #endregion

                    #region RouteData

                    string name;
                    string routeData;
                    var spIndex = nameSpan.Span.IndexOf('/');
                    if (spIndex > -1)
                    {
                        name = nameSpan[..spIndex].ToString();
                        routeData = nameSpan[(spIndex + 1)..].ToString();
                    }
                    else
                    {
                        name = nameSpan.ToString();
                        routeData = null;
                    }

                    #endregion

                    #region Action 404

                    var ok = module.ActionDict.TryGetValue(name.ToLower(), out var action);
                    if (!ok)
                    {
                        context.Response.StatusCode = 404;
                        return;
                    }

                    #endregion

                    #region 405

                    if (action.HttpMethod != context.Request.Method)
                    {
                        context.Response.StatusCode = 405;
                        return;
                    }

                    #endregion

                    //计时器
                    var startTime = Stopwatch.GetTimestamp();

                    var fastCtx = new FastContext(context, module, action, JsonOptionsDefault, routeData, webApp);

                    object[] moduleData = null;

                    /****运行方法处理****/
                    try
                    {
                        #region 开始请求前

                        if (OnRequest != null)
                        {
                            OnRequest.Invoke(fastCtx);
                            if (fastCtx.Ex != null)
                            {
                                //计算执行时间
                                fastCtx.ExecuteTime = FastUtils.GetTotalMilliseconds(startTime);
                                fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested;
                                await AfterAsync(fastCtx);
                                return;
                            }
                        }
                        else if (OnRequestAsync != null)
                        {
                            await OnRequestAsync.Invoke(fastCtx);
                            if (fastCtx.Ex != null)
                            {
                                //计算执行时间
                                fastCtx.ExecuteTime = FastUtils.GetTotalMilliseconds(startTime);
                                fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested;
                                await AfterAsync(fastCtx);
                                return;
                            }
                        }
                        else if (OnRequestValueAsync != null)
                        {
                            await OnRequestValueAsync.Invoke(fastCtx);
                            if (fastCtx.Ex != null)
                            {
                                //计算执行时间
                                fastCtx.ExecuteTime = FastUtils.GetTotalMilliseconds(startTime);
                                fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested;
                                await AfterAsync(fastCtx);
                                return;
                            }
                        }

                        #endregion

                        #region 过滤器

                        if (!fastCtx.ClearFilter && FilterList.Count > 0)
                        {
                            foreach (var item in FilterList)
                            {
                                if (item.Execute != null)
                                {
                                    item.Execute(fastCtx);
                                }
                                else if (item.ExecuteAsync != null)
                                {
                                    await item.ExecuteAsync(fastCtx);
                                }
                                else
                                {
                                    await item.ExecuteValueAsync(fastCtx);
                                }

                                if (fastCtx.Ex != null)
                                {
                                    //计算执行时间
                                    fastCtx.ExecuteTime = FastUtils.GetTotalMilliseconds(startTime);
                                    fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested;
                                    await AfterAsync(fastCtx);
                                    return;
                                }
                            }
                        }

                        #endregion

                        #region Form和Body统一处理

                        //表单
                        if (context.Request.HasFormContentType)
                        {
                            fastCtx.Form = await context.Request.ReadFormAsync();
                        }

                        //是否允许body重复读
                        if (action.EnableBuffering)
                        {
                            context.Request.EnableBuffering();
                        }

                        #endregion

                        #region 赋值参数

                        if (!action.IsStatic && module.ParamList.Count > 0)
                        {
                            moduleData = new object[module.ParamList.Count];

                            for (int i = 0; i < module.ParamList.Count; i++)
                            {
                                var item = module.ParamList[i];

                                if (item.IsCustomerType) //自定义类型
                                {
                                    if (item.Creator != null)
                                    {
                                        if (item.Creator.Create != null)
                                        {
                                            moduleData[i] = item.Creator.Create.Invoke(fastCtx);
                                        }
                                        else if (item.Creator.CreateAsync != null)
                                        {
                                            moduleData[i] = await item.Creator.CreateAsync.Invoke(fastCtx);
                                        }
                                        else
                                        {
                                            moduleData[i] = await item.Creator.CreateValueAsync.Invoke(fastCtx);
                                        }
                                    }
                                    else if (item.Type == typeof(IFastHttp))
                                    {
                                        moduleData[i] = fastCtx.FastHttp;
                                    }
                                    else if (item.Type == typeof(HttpContext))
                                    {
                                        moduleData[i] = context;
                                    }
                                    else if (item.Type == typeof(HttpRequest))
                                    {
                                        moduleData[i] = context.Request;
                                    }
                                    else if (item.Type == typeof(HttpResponse))
                                    {
                                        moduleData[i] = context.Response;
                                    }
                                }
                                else if (item.RequestType == FastParamType.Body)
                                {
                                    if (action.EnableBuffering)
                                    {
                                        context.Request.Body.Position = 0;
                                    }

                                    if (item.IsSimpleType)
                                    {
                                        var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
#if NET6_0
                                        moduleData[i] = await reader.ReadToEndAsync();
#else
                                        moduleData[i] = await reader.ReadToEndAsync(context.RequestAborted);
#endif
                                    }
                                    else
                                    {
                                        moduleData[i] = await JsonSerializer.DeserializeAsync(context.Request.Body, item.Type, JsonOptionsDefault, context.RequestAborted);
                                    }
                                }
                                else if (item.RequestType == FastParamType.Query)
                                {
                                    moduleData[i] = FastUtils.CreateParamQuery(item, context.Request.Query);
                                }
                                else
                                {
                                    moduleData[i] = FastUtils.CreateParamForm(item, fastCtx.Form);
                                }
                            }
                        }

                        if (action.ParamList.Count > 0)
                        {
                            fastCtx.MethodParams = new object[action.ParamList.Count];

                            for (int i = 0; i < action.ParamList.Count; i++)
                            {
                                var item = action.ParamList[i];

                                if (item.IsCustomerType) //自定义类型
                                {
                                    if (item.Creator != null)
                                    {
                                        if (item.Creator.Create != null)
                                        {
                                            fastCtx.MethodParams[i] = item.Creator.Create.Invoke(fastCtx);
                                        }
                                        else if (item.Creator.CreateAsync != null)
                                        {
                                            fastCtx.MethodParams[i] = await item.Creator.CreateAsync.Invoke(fastCtx);
                                        }
                                        else
                                        {
                                            fastCtx.MethodParams[i] = await item.Creator.CreateValueAsync.Invoke(fastCtx);
                                        }
                                    }
                                    else if (item.Type == typeof(IFastHttp))
                                    {
                                        fastCtx.MethodParams[i] = fastCtx.FastHttp;
                                    }
                                    else if (item.Type == typeof(HttpContext))
                                    {
                                        fastCtx.MethodParams[i] = context;
                                    }
                                    else if (item.Type == typeof(HttpRequest))
                                    {
                                        fastCtx.MethodParams[i] = context.Request;
                                    }
                                    else if (item.Type == typeof(HttpResponse))
                                    {
                                        fastCtx.MethodParams[i] = context.Response;
                                    }
                                }
                                else if (item.RequestType == FastParamType.Body)
                                {
                                    if (action.EnableBuffering)
                                    {
                                        context.Request.Body.Position = 0;
                                    }

                                    if (item.IsSimpleType)
                                    {
                                        var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
#if NET6_0
                                        fastCtx.MethodParams[i] = await reader.ReadToEndAsync();
#else
                                        fastCtx.MethodParams[i] = await reader.ReadToEndAsync(context.RequestAborted);
#endif
                                    }
                                    else
                                    {
                                        fastCtx.MethodParams[i] = await JsonSerializer.DeserializeAsync(context.Request.Body, item.Type, JsonOptionsDefault, context.RequestAborted);
                                    }
                                }
                                else if (item.RequestType == FastParamType.Query)
                                {
                                    fastCtx.MethodParams[i] = FastUtils.CreateParamQuery(item, context.Request.Query);
                                }
                                else
                                {
                                    fastCtx.MethodParams[i] = FastUtils.CreateParamForm(item, fastCtx.Form);
                                }
                            }
                        }

                        #endregion

                        #region 执行方法

                        object methodVal;

                        //静态方法
                        if (action.IsStatic)
                        {
                            if (action.ParamList.Count == 0) //无参数
                            {
                                methodVal = action.Invoker(module.Type);
                            }
                            else //有参数
                            {
                                methodVal = action.Invoker(module.Type, fastCtx.MethodParams);
                            }
                        }
                        else //非静态方法
                        {
                            object classObj;
                            if (module.ParamList.Count == 0) //无参数
                            {
                                classObj = module.Invoker();
                            }
                            else //有参数
                            {
                                classObj = module.Invoker(moduleData);
                            }

                            if (action.ParamList.Count == 0) //无参数
                            {
                                methodVal = action.Invoker(classObj);
                            }
                            else //有参数
                            {
                                methodVal = action.Invoker(classObj, fastCtx.MethodParams);
                            }
                        }

                        #endregion

                        #region 方法返回值Task处理

                        if (action.ActionTypeTask == FastActionTypeTask.Default)
                        {
                            fastCtx.ResponseData = methodVal;
                        }
                        else if (action.ActionTypeTask == FastActionTypeTask.Task)
                        {
                            await (Task)methodVal;
                        }
                        else if (action.ActionTypeTask == FastActionTypeTask.TaskT)
                        {
                            var task = (Task)methodVal;
                            await task;
                            fastCtx.ResponseData = FastEmit.FastEmitFactory.GetTaskResult(task);
                        }
                        else if (action.ActionTypeTask == FastActionTypeTask.ValueTask)
                        {
                            await (ValueTask)methodVal;
                        }
                        else
                        {
                            fastCtx.ResponseData = await (dynamic)methodVal;
                        }

                        #endregion

                        //无异常
                        if (fastCtx.Ex == null)
                        {
                            #region 提交事务

                            //提交类参数事务
                            if (module.IsTran && !action.IsStatic && moduleData != null)
                            {
                                for (int i = 0; i < moduleData.Length; i++)
                                {
                                    var par = module.ParamList[i];
                                    if (par.IsTran)
                                    {
                                        var val = moduleData[i];
                                        if (val != null)
                                        {
                                            if (par.Creator.CommitAsync != null)
                                            {
                                                await par.Creator.CommitAsync.Invoke(fastCtx, val);
                                            }
                                            else if (par.Creator.Commit != null)
                                            {
                                                par.Creator.Commit.Invoke(fastCtx, val);
                                            }
                                            else
                                            {
                                                await par.Creator.CommitValueAsync.Invoke(fastCtx, val);
                                            }
                                        }
                                    }
                                }
                            }

                            //提交方法参数事务
                            if (action.IsTran && fastCtx.MethodParams != null)
                            {
                                for (int i = 0; i < fastCtx.MethodParams.Length; i++)
                                {
                                    var par = action.ParamList[i];
                                    if (par.IsTran)
                                    {
                                        var val = fastCtx.MethodParams[i];
                                        if (val != null)
                                        {
                                            if (par.Creator.CommitAsync != null)
                                            {
                                                await par.Creator.CommitAsync.Invoke(fastCtx, val);
                                            }
                                            else if (par.Creator.Commit != null)
                                            {
                                                par.Creator.Commit.Invoke(fastCtx, val);
                                            }
                                            else
                                            {
                                                await par.Creator.CommitValueAsync.Invoke(fastCtx, val);
                                            }
                                        }
                                    }
                                }
                            }

                            #endregion
                        }
                    }
                    catch (Exception ex)
                    {
                        fastCtx.Ex = ex;
                    }

                    //方法有异常回滚事物
                    if (fastCtx.Ex != null)
                    {
                        #region 回滚事务

                        //回滚类参数事务
                        if (module.IsTran && !action.IsStatic && moduleData != null)
                        {
                            for (int i = 0; i < moduleData.Length; i++)
                            {
                                var par = module.ParamList[i];
                                if (par.IsTran)
                                {
                                    try
                                    {
                                        var val = moduleData[i];
                                        if (val != null)
                                        {
                                            if (par.Creator.RollbackAsync != null)
                                            {
                                                await par.Creator.RollbackAsync.Invoke(fastCtx, val);
                                            }
                                            else if (par.Creator.Rollback != null)
                                            {
                                                par.Creator.Rollback.Invoke(fastCtx, val);
                                            }
                                            else
                                            {
                                                await par.Creator.RollbackValueAsync.Invoke(fastCtx, val);
                                            }
                                        }
                                    }
                                    catch { }
                                }
                            }
                        }

                        //回滚方法参数事务
                        if (action.IsTran && fastCtx.MethodParams != null)
                        {
                            for (int i = 0; i < fastCtx.MethodParams.Length; i++)
                            {
                                var par = action.ParamList[i];
                                if (par.IsTran)
                                {
                                    try
                                    {
                                        var val = fastCtx.MethodParams[i];
                                        if (val != null)
                                        {
                                            if (par.Creator.RollbackAsync != null)
                                            {
                                                await par.Creator.RollbackAsync.Invoke(fastCtx, val);
                                            }
                                            else if (par.Creator.Rollback != null)
                                            {
                                                par.Creator.Rollback.Invoke(fastCtx, val);
                                            }
                                            else
                                            {
                                                await par.Creator.RollbackValueAsync.Invoke(fastCtx, val);
                                            }
                                        }
                                    }
                                    catch { }

                                }
                            }
                        }

                        #endregion
                    }

                    #region 释放资源

                    //释放类参数
                    if (module.NeedDispose && !action.IsStatic && moduleData != null)
                    {
                        for (int i = 0; i < moduleData.Length; i++)
                        {
                            var par = module.ParamList[i];
                            if (par.NeedDispose)
                            {
                                try
                                {
                                    var val = moduleData[i];
                                    if (val != null)
                                    {
                                        if (par.Creator.Dispose != null)
                                        {
                                            par.Creator.Dispose.Invoke(fastCtx, val);
                                        }
                                        else if (par.Creator.DisposeAsync != null)
                                        {
                                            await par.Creator.DisposeAsync.Invoke(fastCtx, val);
                                        }
                                        else
                                        {
                                            await par.Creator.DisposeValueAsync.Invoke(fastCtx, val);
                                        }
                                    }
                                }
                                catch { }

                            }
                        }
                    }

                    //释放方法参数
                    if (action.NeedDispose && fastCtx.MethodParams != null)
                    {
                        for (int i = 0; i < fastCtx.MethodParams.Length; i++)
                        {
                            var par = action.ParamList[i];
                            if (par.NeedDispose)
                            {
                                try
                                {
                                    var val = fastCtx.MethodParams[i];
                                    if (val != null)
                                    {
                                        if (par.Creator.Dispose != null)
                                        {
                                            par.Creator.Dispose.Invoke(fastCtx, val);
                                        }
                                        else if (par.Creator.DisposeAsync != null)
                                        {
                                            await par.Creator.DisposeAsync.Invoke(fastCtx, val);
                                        }
                                        else
                                        {
                                            await par.Creator.DisposeValueAsync.Invoke(fastCtx, val);
                                        }
                                    }
                                }
                                catch { }
                            }
                        }
                    }

                    //释放服务
                    if (fastCtx.HasService)
                    {
                        fastCtx._fastHttp.Service.Dispose();
                    }

                    if (fastCtx.HasAsyncService)
                    {
                        await fastCtx._fastHttp.AsyncService.DisposeAsync();
                    }

                    #endregion

                    //计算方法执行时间
                    fastCtx.ExecuteTime = FastUtils.GetTotalMilliseconds(startTime);

                    //方法有异常直接返回
                    if (fastCtx.Ex != null)
                    {
                        //用户自定义响应
                        if (fastCtx.Customer || action.ActionType == FastActionType.Customer)
                        {
                            if (context.Response.HasStarted)
                            {
                                try
                                {
                                    //关闭客户端连接
                                    context.Abort();
                                }
                                catch { }
                            }
                            else
                            {
                                //还未响应设置500错误
                                context.Response.StatusCode = 500;
                            }
                            fastCtx.CanResponse = false;
                        }
                        else
                        {
                            fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested && !context.Response.HasStarted;
                        }

                        await AfterAsync(fastCtx);
                        return;
                    }

                    #region 重置计时器

                    startTime = Stopwatch.GetTimestamp();

                    #endregion

                    /****方法运行结果处理****/
                    try
                    {
                        #region 响应处理

                        if (!fastCtx.Customer && action.ActionType != FastActionType.Customer)
                        {
                            if (action.ActionType == FastActionType.Default) //默认
                            {
                                //开始响应前
                                if (action.IsJsonStream)
                                {
                                    await context.Response.WriteAsJsonAsync(fastCtx.ResponseData, JsonOptionsDefault, context.RequestAborted);
                                }
                                else if (OnResponseAsync != null)
                                {
                                    await OnResponseAsync(fastCtx);
                                }
                                else
                                {
                                    await context.Response.WriteAsJsonAsync(fastCtx.ResponseData, JsonOptionsDefault, context.RequestAborted);
                                }
                            }
                            else if (action.ActionType == FastActionType.Redirect) //跳转
                            {
                                context.Response.StatusCode = 302;
                                context.Response.Headers.Location = (string)fastCtx.ResponseData;
                            }
                            else if (action.ActionType == FastActionType.View) //视图
                            {
                                if (OnViewAsync != null)
                                {
                                    var view = (FastView)fastCtx.ResponseData;
                                    await OnViewAsync.Invoke(fastCtx, view);
                                }
                            }
                        }

                        #endregion
                    }
                    catch (Exception ex)
                    {
                        fastCtx.Ex = ex;
                    }

                    #region 计算序列化时间

                    fastCtx.SerialTime = FastUtils.GetTotalMilliseconds(startTime);

                    #endregion

                    fastCtx.CanResponse = !context.RequestAborted.IsCancellationRequested && !context.Response.HasStarted;
                    await AfterAsync(fastCtx);

                });
            });
        }

        #endregion

        #region MyRegion

        public JsonSerializerOptions JsonOptionsDefault { get; set; } = new()
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            NumberHandling = JsonNumberHandling.AllowReadingFromString,
            PropertyNameCaseInsensitive = true,
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null
        };

        public readonly JsonSerializerOptions JsonOptions = new()
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            NumberHandling = JsonNumberHandling.AllowReadingFromString,
            PropertyNameCaseInsensitive = true,
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null
        };

        public readonly JsonSerializerOptions JsonOptionsMs = new()
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            NumberHandling = JsonNumberHandling.AllowReadingFromString,
            PropertyNameCaseInsensitive = true,
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null
        };

        public readonly JsonSerializerOptions JsonOptionsNs = new()
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            NumberHandling = JsonNumberHandling.AllowReadingFromString,
            PropertyNameCaseInsensitive = true,
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null
        };

        public readonly JsonSerializerOptions JsonOptionsWeb = new()
        {
            //Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), //不编码中文
            //PropertyNamingPolicy = null, //null序列化属性名称不变,小写JsonNamingPolicy.CamelCase
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, //不编码中文和html标签
            NumberHandling = JsonNumberHandling.AllowReadingFromString, //反序列化时允许string转数字
            PropertyNameCaseInsensitive = true, //true反序列化忽略大小写(开销大)
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
        };

        public readonly JsonSerializerOptions JsonOptionsComment = new()
        {
            //Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), //不编码中文
            //PropertyNamingPolicy = null, //序列化属性不转小写
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,//不编码中文和html
            NumberHandling = JsonNumberHandling.AllowReadingFromString, //反序列化时允许string转数字
            PropertyNameCaseInsensitive = true, //反序列化忽略大小写
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null,
            AllowTrailingCommas = true, //允许尾部逗号
            ReadCommentHandling = JsonCommentHandling.Skip //跳过注释
        };

        public readonly JsonSerializerOptions JsonOptionsIndented = new()
        {
            //Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), //不编码中文
            //PropertyNamingPolicy = null, //序列化属性不转小写
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,//不编码中文和html
            NumberHandling = JsonNumberHandling.AllowReadingFromString, //反序列化时允许string转数字
            PropertyNameCaseInsensitive = true, //反序列化忽略大小写
            PropertyNamingPolicy = null,
            DictionaryKeyPolicy = null,
            AllowTrailingCommas = true, //允许尾部逗号
            ReadCommentHandling = JsonCommentHandling.Skip, //跳过注释
            WriteIndented = true
        };

        /// <summary>
        /// 开始请求前
        /// </summary>
        public event Action<FastContext> OnRequest;

        /// <summary>
        /// 开始请求前Task
        /// </summary>
        public event Func<FastContext, Task> OnRequestAsync;

        /// <summary>
        /// 开始请求前ValueTask
        /// </summary>
        public event Func<FastContext, ValueTask> OnRequestValueAsync;

        /// <summary>
        /// 开始响应前
        /// </summary>
        public event Func<FastContext, Task> OnResponseAsync;

        /// <summary>
        /// 请求结束后
        /// </summary>
        public event Func<FastContext, ValueTask> OnAfterRequestAsync;

        /// <summary>
        /// 视图事件
        /// </summary>
        public event Func<FastContext, FastView, Task> OnViewAsync;

        #endregion

        public bool EnableBuffer { get; set; } = false;

        public string BaseDirectory { get; }

        public bool IsDevelopment { get; }

        public bool IsProduction { get; }

        public string ContentRootPath { get; }

        public string WebRootPath { get; }

        public FastApp(WebApplication webApp)
        {
            this.webApp = webApp;
            BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            IsDevelopment = webApp.Environment.IsDevelopment();
            IsProduction = webApp.Environment.IsProduction();
            ContentRootPath = webApp.Environment.ContentRootPath + Path.DirectorySeparatorChar;
            WebRootPath = webApp.Environment.WebRootPath + Path.DirectorySeparatorChar;

            JsonOptionsDefault.Converters.Add(new DateTimeConverter());
            JsonOptionsDefault.Converters.Add(new DateTimeOffsetConverter());

            JsonOptions.Converters.Add(new DateTimeConverter());
            JsonOptions.Converters.Add(new DateTimeOffsetConverter());

            JsonOptionsMs.Converters.Add(new DateTimeMsConverter());
            JsonOptionsMs.Converters.Add(new DateTimeOffsetMsConverter());

            JsonOptionsNs.Converters.Add(new DateTimeNsConverter());
            JsonOptionsNs.Converters.Add(new DateTimeOffsetNsConverter());

            JsonOptionsWeb.Converters.Add(new DateTimeConverter());
            JsonOptionsWeb.Converters.Add(new DateTimeOffsetConverter());

            JsonOptionsComment.Converters.Add(new DateTimeConverter());
            JsonOptionsComment.Converters.Add(new DateTimeOffsetConverter());

            JsonOptionsIndented.Converters.Add(new DateTimeConverter());
            JsonOptionsIndented.Converters.Add(new DateTimeOffsetConverter());

            AddParams(typeof(IServiceProvider), new FastParamCreator
            {
                Create = ctx => webApp.Services
            });

            AddParams(typeof(IServiceScope), new FastParamCreator
            {
                Create = ctx =>
                {
                    return webApp.Services.CreateScope();
                },
                Dispose = (ctx, obj) =>
                {
                    var scope = (IServiceScope)obj;
                    scope.Dispose();
                }
            });

            AddParams(typeof(AsyncServiceScope), new FastParamCreator
            {
                Create = ctx =>
                {
                    return webApp.Services.CreateAsyncScope();
                },
                DisposeValueAsync = (ctx, obj) =>
                {
                    var scope = (AsyncServiceScope)obj;
                    return scope.DisposeAsync();
                }
            });
        }

        /// <summary>
        /// 添加参数
        /// </summary>
        /// <param name="type"></param>
        /// <param name="creator"></param>
        public void AddParams(Type type, FastParamCreator creator)
        {
            ParamCreatorDict.Add(type.TypeHandle, creator);
        }

        /// <summary>
        /// 添加过滤器
        /// </summary>
        /// <param name="filter"></param>
        public void AddFilter(FastFilter filter)
        {
            FilterList.Add(filter);
        }

        /// <summary>
        /// 添加路由
        /// </summary>
        /// <param name="route"></param>
        /// <param name="type"></param>
        public void AddRoute(string route, Type type)
        {
            if (!route.StartsWith('/'))
            {
                route = "/" + route;
            }

            if (!route.EndsWith('/'))
            {
                route += "/";
            }

            route = route.ToLower();
            FastUtils.AddType(route, type, this);
            MapRoute(route);
        }

        /// <summary>
        /// 添加路由
        /// </summary>
        /// <param name="type"></param>
        /// <param name="prefix"></param>
        public void AddRoute(Type type, string prefix = "")
        {
            var routeAttr = type.GetCustomAttribute<FastRouteAttribute>(false);
            if (routeAttr == null)
            {
                throw new Exception($"FastRouteAttribute is not define at {type.FullName}");
            }

            string route = routeAttr.Name;

            if (!route.StartsWith('/'))
            {
                route = "/" + route;
            }
            if (!route.EndsWith('/'))
            {
                route += "/";
            }

            if (!string.IsNullOrEmpty(prefix))
            {
                if (!prefix.StartsWith('/'))
                {
                    prefix = "/" + prefix;
                }

                if (prefix.EndsWith('/'))
                {
                    prefix = prefix[..prefix.LastIndexOf('/')];
                }
            }

            route = prefix + route;

            AddRoute(route, type);
        }

        /// <summary>
        /// 添加路由Type[]
        /// </summary>
        /// <param name="types"></param>
        /// <param name="prefix"></param>
        public void AddRoute(Type[] types, string prefix = "")
        {
            if (!string.IsNullOrEmpty(prefix))
            {
                if (!prefix.StartsWith('/'))
                {
                    prefix = "/" + prefix;
                }

                if (prefix.EndsWith('/'))
                {
                    prefix = prefix[..prefix.LastIndexOf('/')];
                }
            }

            Dictionary<string, Type> dict = [];

            foreach (var type in types)
            {
                var routeAttr = type.GetCustomAttribute<FastRouteAttribute>(false);
                if (routeAttr == null)
                {
                    continue;
                }
                string route = routeAttr.Name;
                if (!route.StartsWith('/'))
                {
                    route = "/" + route;
                }

                if (!route.EndsWith('/'))
                {
                    route += "/";
                }

                dict.Add(route, type);
            }

            if (dict.Count > 0)
            {
                var sortList = dict.Keys.OrderBy(b => b[..(b.IndexOf('/', 1) + 1)]).ThenByDescending(b => b.Length);
                foreach (var item in sortList)
                {
                    AddRoute(prefix + item, dict[item]);
                }
            }
        }

        /// <summary>
        ///  添加程序集路由
        /// </summary>
        /// <param name="assambly"></param>
        /// <param name="prefix"></param>
        public void AddRoute(Assembly assambly, string prefix = "")
        {
            AddRoute(assambly.GetTypes(), prefix);
        }

    }
}
